package im.dhc.gitdiff.util;

import java.io.File;
import java.util.List;

import org.eclipse.jgit.api.DiffCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;

public class GitUtil {
	private static String rootdir;
	private static String branchName;
	private static String username;
	private static String password;

	static {
		PropertityUtil propertityUtil;
		try {
			propertityUtil = new PropertityUtil();
			rootdir = propertityUtil.getProperty("rootdir");
			branchName = propertityUtil.getProperty("branchName");
			username = propertityUtil.getProperty("username");
			password = propertityUtil.getProperty("password");
			propertityUtil = null;
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	public GitUtil() {
		
	}
	
	/**
	 * 本地已存在git库时的创建
	 * @return
	 * @throws Exception
	 */
	public static Git gitInit() throws Exception {
		FileRepositoryBuilder builder = new FileRepositoryBuilder();
        Repository repository = builder.setGitDir(new File(getGitDir(rootdir)))
        		.readEnvironment()
        		.findGitDir()
        		.build();

        Git git = new Git(repository);
		return git;
	}
	
	/**
	 * 切换分支（已存在该分支）
	 * @param git
	 * @param branchName
	 * @throws Exception
	 */
	public static void checkOut(Git git , String branchName) throws Exception {
		git.checkout().setCreateBranch(false).setName(branchName).call();
	}
	
	/**
	 * 拉取代码
	 * @param git
	 * @throws Exception
	 */
	public static void fetch(Git git) throws Exception {
		git.fetch().setRemote("origin")
		.setCredentialsProvider(new UsernamePasswordCredentialsProvider(username,password))
		.call();
	}
	
	/**
	 * 拉取并合并代码
	 * @param git
	 * @throws Exception
	 */
	public static void pull(Git git) throws Exception{
		git.pull().setRemoteBranchName(branchName)
		.setCredentialsProvider(new UsernamePasswordCredentialsProvider(username,password))
		.call();
	}
	
	/**
	 * 比较两个版本之间的差异
	 * @param git
	 * @param newVersion
	 * @param oldVersion
	 * @return
	 * @throws Exception
	 */
	public static List<DiffEntry> diffTwoVersion(Git git,String newVersion,String oldVersion) throws Exception{
		ObjectReader reader = git.getRepository().newObjectReader();

        CanonicalTreeParser newTreeParser = new CanonicalTreeParser();
        ObjectId newTree = git.getRepository().resolve(newVersion+"^{tree}");
        newTreeParser.reset(reader,newTree);

        CanonicalTreeParser oldTreeParser = new CanonicalTreeParser();
        ObjectId oldTree = git.getRepository().resolve(oldVersion+"^{tree}");
        oldTreeParser.reset(reader,oldTree);

        DiffCommand diffCmd = git.diff().setNewTree(newTreeParser).setOldTree(oldTreeParser);

        diffCmd.setShowNameAndStatusOnly(true);

        List<DiffEntry> diffs = diffCmd.call();
        return diffs;
	}
	
	/**
	 * 比较最新代码和某一版本之间的差异
	 * @param git
	 * @param oldVersion
	 * @return
	 * @throws Exception
	 */
	public static List<DiffEntry> diffHeadAndVersion(Git git,String oldVersion) throws Exception{
		checkOut(git,branchName);
		pull(git);
		ObjectReader reader = git.getRepository().newObjectReader();

        CanonicalTreeParser newTreeParser = new CanonicalTreeParser();
        ObjectId newTree = git.getRepository().resolve("HEAD^{tree}");
        newTreeParser.reset(reader,newTree);

        CanonicalTreeParser oldTreeParser = new CanonicalTreeParser();
        ObjectId oldTree = git.getRepository().resolve(oldVersion+"^{tree}");
        oldTreeParser.reset(reader,oldTree);

        DiffCommand diffCmd = git.diff().setNewTree(newTreeParser).setOldTree(oldTreeParser);

        diffCmd.setShowNameAndStatusOnly(true);

        List<DiffEntry> diffs = diffCmd.call();
        return diffs;
	}
	
	/**
	 * 比较两个分支之间的差异
	 * @param git
	 * @param newBranchRef
	 * @param oldBranchRef
	 * @return
	 * @throws Exception
	 */
	public static List<DiffEntry> diffTwoBranch(Git git,String newBranchRef,String oldBranchRef) throws Exception{
		ObjectReader reader = git.getRepository().newObjectReader();
		
        CanonicalTreeParser newTreeParser = new CanonicalTreeParser();
        ObjectId newTree = git.getRepository().resolve(newBranchRef+"^{tree}");
        newTreeParser.reset(reader,newTree);

        CanonicalTreeParser oldTreeParser = new CanonicalTreeParser();
        ObjectId oldTree = git.getRepository().resolve(oldBranchRef+"^{tree}");
        oldTreeParser.reset(reader,oldTree);

        DiffCommand diffCmd = git.diff().setNewTree(newTreeParser).setOldTree(oldTreeParser);

        diffCmd.setShowNameAndStatusOnly(true);

        List<DiffEntry> diffs = diffCmd.call();
        return diffs;
	} 
	
	/**
	 * 获取git目录
	 * @param dir
	 * @return
	 */
	public static String getGitDir(String dir) {
		return dir+"/.git";
	}

	/**
	 * 取得本地分支的引用
	 * @param branchName
	 * @return
	 */
	public static String getLocalBranchRef(String branchName) {
		return "refs/heads/"+branchName;
	}
	
	/**
	 * 取得远程分支的引用
	 * @param branchName
	 * @return
	 */
	public static String getRemoteBranchRef(String branchName) {
		return "refs/remotes/origin/"+branchName;
	}
	
	public static String getRootdir() {
		return rootdir;
	}

	public static void setRootdir(String rootdir) {
		GitUtil.rootdir = rootdir;
	}

	public static String getBranchName() {
		return branchName;
	}

	public static void setBranchName(String branchName) {
		GitUtil.branchName = branchName;
	}

	public static String getUsername() {
		return username;
	}

	public static void setUsername(String username) {
		GitUtil.username = username;
	}

	public static String getPassword() {
		return password;
	}

	public static void setPassword(String password) {
		GitUtil.password = password;
	}
}
